﻿#include <algorithm>
#include "datastream.h"

DataInputStream::DataInputStream(InputStream * next):InputStream(next)
{

}

int DataInputStream::doRead(unsigned char * buffer, int readLen) throw(StreamException)
{
	auto next = GetNext();
	if (next) {
		return next->read(buffer, readLen);
	}
	return 0;
}

DataInputStream & DataInputStream::operator>>(std::string & t) throw(StreamException)
{
	int size;
	(*this)>> size;
	t.resize(size, 0);
	int readLen = (*this).read((unsigned char*)t.data(), size);

	if (readLen != size) {
		throw ParseException("Parse Error");
	}

	return (*this);
}

DataInputStream & DataInputStream::operator>>(std::wstring & t) throw(StreamException)
{
	int size;
	(*this) >> size;
	t.resize(size);

	unsigned short *buffer = new unsigned short[size];
	int readLen = sizeof(unsigned short) * size;
	int len = (*this).read((unsigned char*)& buffer, readLen);

	if (len != readLen) {
		delete[] buffer;
		throw ParseException("Parse Error");
	}

	t.resize(size);

	for (int i = 0; i < size; i++) {
		t[i] = buffer[i];
	}

	delete[] buffer;
}

DataInputStream & DataInputStream::operator>>(ByteArray & t) throw(StreamException)
{
	int size;
	(*this)>> size;
	t.resize(size, 0);
	int readLen = (*this).read((unsigned char*)t.data(), size);

	if (readLen != size) {
		throw ParseException("Parse Error");
	}

	return (*this);
}

DataOutputStream::DataOutputStream(OutputStream * next):OutputStream(next)
{
}

void DataOutputStream::write(const unsigned char * buffer, int len) throw(StreamException)
{
	auto next = GetNext();
	if (next) {
		next->write(buffer, len);
	}
}

DataOutputStream & DataOutputStream::operator<<(const std::string & t)
{
	int size = t.size();
	(*this) << size;
	(*this).write((const unsigned char*)t.data(), size);
	return (*this);
}

DataOutputStream & DataOutputStream::operator<<(const std::wstring & t)
{
	int size = t.size();
	(*this)<< size;
	auto r = t[0];

	unsigned char buffer_s[4096];
	unsigned char* buffer;
	bool alloc = false;
	int neededSize = t.size() * 2;

	if (neededSize > sizeof(buffer_s)) {
		buffer = new unsigned char[neededSize];
		alloc = true;
	}
	else {
		buffer = buffer_s;
		alloc = false;
	}

	auto dst = (unsigned short*)buffer;

	for (int i = 0; i < size; i++) {
		unsigned short value = t[i];
		dst[i] = t[i];
	}

	(*this).write(buffer, neededSize);
	if (alloc) {
		delete[] buffer;
	}

	return (*this);
}

DataOutputStream & DataOutputStream::operator<<(const ByteArray & t)
{
	int size = t.size();
	(*this) << size;
	(*this).write((const unsigned char*)t.data(), size);
	return (*this);
}

ParseException::ParseException(const char * msg):StreamException(msg)
{
}
